home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
vector.lha
/
vector
/
hmatrix.h
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-23
|
9KB
|
288 lines
#ifndef _HMATRIX_H
#define _HMATRIX_H
#include "cmatrix.h"
#include "hvector.h"
#define HomogenousMatrixDeclare(T) \
class HMat(T) { \
protected: \
T m[4][4]; \
\
public: \
enum { columns, rows }; \
\
HMat(T)() {} \
HMat(T)(int flag, \
const HVec(T) &x, \
const HVec(T) &y, \
const HVec(T) &z, \
const HVec(T) &w); \
\
const T *operator()(int i) const { \
return m[i]; \
} \
T *operator[](int i) { return m[i]; } \
HMat(T) &zero(); \
HMat(T) &identity(); \
\
HMat(T) transpose() const; \
\
/* Dehomogenize a matrix */ \
operator CMat(T)() const; \
\
/* Homogenize a matrix */ \
HMat(T)(const CMat(T) &v); \
}; \
\
HVec(T) operator*(const HMat(T) &m, const HVec(T) &v); \
HVec(T) operator*(const HVec(T) &v, const HMat(T) &m); \
HMat(T) operator*(const HMat(T) &a, const HMat(T) &b); \
/* These are for transformation matrices */ \
inline HMat(T) operator*( \
const HMat(T) &a, \
const CMat(T) &b) \
{ \
return a * HMat(T)(b); \
} \
inline HMat(T) operator*( \
const CMat(T) &a, \
const HMat(T) &b) \
{ \
return HMat(T)(a) * b; \
} \
\
/* Only implemented for HMat(float) */ \
HMat(T) adjoint(const HMat(T) &m, T *det = NULL); \
\
HMat(T) view_matrix( \
const HVec(T) &eye, \
const HVec(T) &lookat, \
const HVec(T) &vup); \
HMat(T) perspective_matrix(T fov, T znear, T zfar); \
HMat(T) screen_matrix(T size, T offset); \
\
ostream &operator<<(ostream &o, const HMat(T) &m);
#define HomogenousMatrixImplement(T) \
\
static const int \
X = 0, \
Y = 1, \
Z = 2, \
W = 3; \
\
/* Initialize a matrix by either columns or rows */ \
HMat(T)::HMat(T)( \
int flag, \
const HVec(T) &x, \
const HVec(T) &y, \
const HVec(T) &z, \
const HVec(T) &w) \
{ \
for (int i = X; i <= W; i++) { \
if (flag == HMat(T)::columns) { \
m[i][X] = x(i); \
m[i][Y] = y(i); \
m[i][Z] = z(i); \
m[i][W] = w(i); \
} else if (flag == HMat(T)::rows) { \
m[X][i] = x(i); \
m[Y][i] = y(i); \
m[Z][i] = z(i); \
m[W][i] = w(i); \
} else { \
cerr << "HMat(T)::HMat(T): bad flag " \
<< "(not rows or columns)" << endl; \
zero(); \
} \
} \
} \
\
HMat(T) &HMat(T)::zero() { \
for (int i = X; i <= W ; i++) \
for (int j = X; j <= W; j++) \
m[i][j] = 0; \
return *this; \
} \
\
HMat(T) &HMat(T)::identity() { \
for (int i = X; i <= W ; i++) \
for (int j = X; j <= W; j++) \
m[i][j] = (i == j); \
return *this; \
} \
\
/* Return the transpose of a matrix */ \
HMat(T) HMat(T)::transpose() const { \
HMat(T) tran; \
\
for (int i = X; i <= W; i++) \
for (int j = X; j <= W; j++) \
tran[i][j] = m[j][i]; \
\
return tran; \
} \
\
/* Dehomogenize a matrix */ \
HMat(T)::operator CMat(T)() const { \
CMat(T) res; \
\
for (int i = X; i <= Z; i++) \
for (int j = X; j <= W; j++) \
res[i][j] = m[i][j]; \
\
return res; \
} \
\
HMat(T)::HMat(T)(const CMat(T) &v) { \
for (int i = X; i <= Z; i++) \
for (int j = X; j <= W; j++) \
m[i][j] = v(i)[j]; \
\
/* No perspective component */ \
m[W][X] = m[W][Y] = m[W][Z] = 0; \
m[W][W] = 1; \
} \
\
/* M = M * V */ \
HVec(T) operator*(const HMat(T) &m, const HVec(T) &v) { \
return HVec(T)( \
m(X)[X]*v(X)+m(X)[Y]*v(Y)+m(X)[Z]*v(Z)+m(X)[W]*v(W), \
m(Y)[X]*v(X)+m(Y)[Y]*v(Y)+m(Y)[Z]*v(Z)+m(Y)[W]*v(W), \
m(Z)[X]*v(X)+m(Z)[Y]*v(Y)+m(Z)[Z]*v(Z)+m(Z)[W]*v(W), \
m(W)[X]*v(X)+m(W)[Y]*v(Y)+m(W)[Z]*v(Z)+m(W)[W]*v(W)); \
} \
\
/* M = V * M */ \
HVec(T) operator*(const HVec(T) &v, const HMat(T) &m) { \
return HVec(T)( \
m(X)[X]*v(X)+m(Y)[X]*v(Y)+m(Z)[X]*v(Z)+m(W)[X]*v(W), \
m(X)[Y]*v(X)+m(Y)[Y]*v(Y)+m(Z)[Y]*v(Z)+m(W)[Y]*v(W), \
m(X)[Z]*v(X)+m(Y)[Z]*v(Y)+m(Z)[Z]*v(Z)+m(W)[Z]*v(W), \
m(X)[W]*v(X)+m(Y)[W]*v(Y)+m(Z)[W]*v(Z)+m(W)[W]*v(W)); \
} \
\
/* M = M * M */ \
HMat(T) operator*(const HMat(T) &a, const HMat(T) &b) { \
HMat(T) res; \
\
for (int i = X; i <= W; i++) { \
for (int j = X; j <= W; j++) { \
res[i][j] = 0; \
for (int k = X; k <= W; k++) \
res[i][j] += a(i)[k] * b(k)[j]; \
} \
} \
\
return res; \
} \
\
/* Construct a viewing matrix which effects a translation \
* of the eye to the origin, the lookat - eye vector to \
* the -Z axis, and the vup vector to the +Y axis. \
* This is drawn from PPHIGS but done in RHS. \
*/ \
HMat(T) view_matrix( \
const HVec(T) &eye, \
const HVec(T) &lookat, \
const HVec(T) &vup) \
{ \
static HVec(T) zero(0,0,0,1); \
HVec(T) w = eye - lookat; /* Look vector */ \
\
/* Translate eye to origin */ \
HMat(T) trans; \
trans.identity(); \
trans = trans * translation_matrix(-eye); \
\
/* Construct an orthogonal basis whose up \
* vector v is as close to vup as possible \
*/ \
HVec(T) u = vup ^ w; \
HVec(T) v = w ^ u; \
\
u.normalize(); u[W] = 0; \
v.normalize(); v[W] = 0; \
w.normalize(); w[W] = 0; \
\
HMat(T) frame(HMat(T)::rows, u, v, w, zero); \
\
return frame * trans; \
} \
\
/* Construct a Blinn-style perspective matrix, with specified \
* near and far clipping planes and field of view (in degrees): \
* \
* | cos theta 0 0 0 | \
* | | \
* | | \
* | 0 cos theta 0 0 | \
* | | \
* | sin theta Zf sin theta Zf Zn | \
* | 0 0 ------------ --------------- | \
* | Zf - Zn Zf - Zn | \
* | | \
* | 0 0 sin theta 0 | \
* \
* This transforms into the canonical [-1..1]^2 window. Z \
* *decreases* with increasing depth in world space, and \
* *increases* with increasing depth in screen space \
* x' = tan theta x/-z \
* y' = tan theta y/-z \
* Zf Zn \
* z' = ------- (1 + --) -> z'(-Zn) = 0, z'(-Zf) = 1 \
* Zf - Zn z \
*/ \
HMat(T) perspective_matrix(float fov, float Zn, float Zf) { \
fov = dtor(fov); \
\
float ct = cos(fov/2), st = sin(fov/2), \
zs = st * Zf / (Zf - Zn); \
HMat(T) p; \
\
p.zero(); \
/* Note that the third column is all negated so Z \
* increases away from the eye (in RHS, we look \
* down -Z instead of +Z). \
*/ \
p[X][X] = ct; \
p[Y][Y] = ct; \
p[Z][Z] =-zs; p[Z][W] =-zs * Zn; \
p[W][Z] =-st; \
\
return p; \
} \
\
/* Construct a matrix that transforms from the canonical \
* [-1..1]^2 window to a window of specified size and offset. \
*/ \
HMat(T) screen_matrix(float size, float offset) { \
HMat(T) p; \
\
p.zero(); \
p[X][X] = size/2; p[X][W] = offset; \
p[Y][Y] = size/2; p[Y][W] = offset; \
p[Z][Z] = 1; \
p[W][W] = 1; \
\
return p; \
} \
\
ostream &operator<<(ostream &o, const HMat(T) &m) { \
for (int i = X; i <= W; i++) \
o << '\t' << "( " \
<< setw(8) << m(i)[X] << ' ' \
<< setw(8) << m(i)[Y] << ' ' \
<< setw(8) << m(i)[Z] << ' ' \
<< setw(8) << m(i)[W] << " )\n"; \
\
return o; \
}
HomogenousMatrixDeclare(float);
typedef HMat(float) HMatrix;
#endif /*_HMATRIX_H*/